﻿#pragma once
#include "VertexIndexBuffer.h"
#include <map>
#include <memory>

/**
VertexStreamAttribute用于指定绘图的顶点属性
这些属性将应用于glVertexAttribPointer()
*/
struct VertexStreamAttribute
{
    /**
     构造函数
     */
    VertexStreamAttribute()
        : _normalize(false), _offset(0), _semantic(0), _type(0), _size(0)
    {
    }
    /**
     构造函数
     @param offset 属性的偏移
     @param semantic 属性位置、纹理、颜色等(着色器中的变量索引)
     @param type 属性的类型，可以是 GL_FLOAT 类型
     @param size 描述属性有多少参数类型(元素个数)
     */
    VertexStreamAttribute(int offset, int semantic, int type, int size)
        : _normalize(false), _offset(offset), _semantic(semantic), _type(type), _size(size)
    {
    }
    /**
     构造函数
     @param offset 属性的偏移
     @param semantic 属性位置、纹理、颜色等(着色器中的变量索引)
     @param type 属性的类型,可以是 GL_FLOAT 类型
     @param size 描述属性有多少参数类型
     @param normalize 如果是true,数据将被255除
     */
    VertexStreamAttribute(int offset, int semantic, int type, int size, bool normalize)
        : _normalize(normalize), _offset(offset), _semantic(semantic), _type(type), _size(size)
    {
    }
    /**
     属性是否被标准化
     */
    bool _normalize;
    /**
     在属性缓存中的偏移值
     */
    int _offset;
    /**
     描述属性的用处,可能是位置、颜色等
     */
    int _semantic;
    /**
     属性类型的描述,可能是 GL_FLOAT、GL_UNSIGNED_BYTE 等
     */
    int _type;
    /**
     描述在属性中有多少元素的类型
     */
    int _size;
};

/**
VertexData用于为GPU指定输入流,
一个VertexData将由多个流组成,
每个流将包含一个VertexStreamAttribute以及VertexBuffer.
流将使用semantic做为ID.
*/

class VertexData
{
public:
    /**
    创建VertexData的实例
    */
    static VertexData* create();
    /**
    获取VertexData中流的数量
    */
    size_t getVertexStreamCount() const;
    /**
    将一个流写入VertexData，流通过semantic进行区分，
    因此，如果之前没有指定semantic，它将添加一个流，或者覆盖旧的流。
    @param buffer 流的绑定缓冲区
    @param stream 绑定顶点属性，其成员变量semantic将用作标识符。
    */
    bool setStream(std::shared_ptr<VertexBuffer>& buffer, const VertexStreamAttribute& stream);
    /**
    删除指定的流
    @param semantic 流的semantic 
    */
    void removeStream(int semantic);
    /**
    获取流的属性
    @param semantic 流的semantic
    */
    VertexStreamAttribute* getStreamAttribute(int semantic);
    /**
    获取流的数据缓冲区
    @param semantic 流的semantic
    */
    std::shared_ptr<VertexBuffer>& getStreamBuffer(int semantic);
    /**
    渲染时调用，它将顶点数据的状态绑定到当前渲染管道。
    */
    void use();

    VertexData();
    virtual ~VertexData();

protected:
    /**
    数据流的结构体
    */
    struct BufferAttribute
    {
        std::shared_ptr<VertexBuffer> _buffer;
        VertexStreamAttribute _stream;
    };

    /**
    数据流
    */
    std::map<int, BufferAttribute> _vertexStreams;
};
